using System.Net;
using System.Net.Sockets;
using System.Text;

namespace MauiBuilder.Services;

/// <summary>
/// Socket连接配置类
/// 包含所有Socket连接相关的配置参数
/// </summary>
public class SocketConfig
{
    /// <summary>
    /// 服务器地址
    /// 支持IP地址或域名
    /// 默认值：192.168.10.121
    /// </summary>
    public string ServerAddress { get; set; } = "192.168.10.121";
    
    /// <summary>
    /// 服务器端口号
    /// 有效范围：1-65535
    /// 默认值：1605
    /// </summary>
    public int ServerPort { get; set; } = 1605;
    
    /// <summary>
    /// 连接超时时间（毫秒）
    /// 超过此时间未连接成功将抛出超时异常
    /// 建议范围：3000-10000ms
    /// 默认值：5000ms（5秒）
    /// </summary>
    public int ConnectTimeoutMs { get; set; } = 5000;
    
    /// <summary>
    /// 数据接收超时时间（毫秒）
    /// 超过此时间未收到数据将触发重连机制
    /// 建议范围：10000-60000ms
    /// 默认值：60000ms（60秒）
    /// </summary>
    public int ReceiveTimeoutMs { get; set; } = 60000;
    
    /// <summary>
    /// 数据缓冲区大小（字节）
    /// 影响单次接收数据的最大长度
    /// 建议范围：512-8192字节
    /// 默认值：1024字节（1KB）
    /// </summary>
    public int BufferSize { get; set; } = 1024;
    
    /// <summary>
    /// 最大重连尝试次数
    /// 连接失败时的最大重试次数
    /// 0表示不重连，-1表示无限重连
    /// 默认值：3次
    /// </summary>
    public int MaxReconnectAttempts { get; set; } = 3;
    
    /// <summary>
    /// 重连延迟时间（毫秒）
    /// 每次重连尝试之间的等待时间
    /// 建议范围：1000-5000ms
    /// 默认值：2000ms（2秒）
    /// </summary>
    public int ReconnectDelayMs { get; set; } = 2000;
    
    /// <summary>
    /// 验证配置参数是否有效
    /// </summary>
    /// <returns>配置是否有效</returns>
    public bool IsValid()
    {
        return !string.IsNullOrWhiteSpace(ServerAddress) &&
               ServerPort > 0 && ServerPort <= 65535 &&
               ConnectTimeoutMs > 0 &&
               ReceiveTimeoutMs > 0 &&
               BufferSize > 0 &&
               MaxReconnectAttempts >= -1 &&
               ReconnectDelayMs >= 0;
    }
    
    /// <summary>
    /// 获取配置信息的字符串表示
    /// </summary>
    /// <returns>配置信息</returns>
    public override string ToString()
    {
        return $"Server: {ServerAddress}:{ServerPort}, " +
               $"ConnectTimeout: {ConnectTimeoutMs}ms, " +
               $"ReceiveTimeout: {ReceiveTimeoutMs}ms, " +
               $"BufferSize: {BufferSize}B, " +
               $"MaxReconnect: {MaxReconnectAttempts}, " +
               $"ReconnectDelay: {ReconnectDelayMs}ms";
    }
}

/// <summary>
/// Socket状态回调接口
/// </summary>
public interface ISocketStateCallback
{
    void OnSocketStateChanged(bool isConnected);
    void OnSocketMessageReceived(string message);
    void OnSocketError(string error);
}

/// <summary>
/// Socket客户端管理器
/// 负责TCP Socket连接、数据收发和状态管理
/// 使用原生.NET TcpClient实现
/// </summary>
public class SocketManager : IDisposable
{
    /// <summary>
    /// 连接配置
    /// </summary>
    private SocketConfig _config;
    
    /// <summary>
    /// TCP客户端
    /// </summary>
    private TcpClient? _tcpClient;
    
    /// <summary>
    /// Socket连接状态
    /// </summary>
    private volatile bool _isConnected = false;
    
    /// <summary>
    /// 状态回调接口
    /// </summary>
    private ISocketStateCallback? _callback;
    
    /// <summary>
    /// 数据接收任务取消令牌
    /// </summary>
    private CancellationTokenSource? _cancellationTokenSource;
    
    /// <summary>
    /// 线程锁
    /// </summary>
    private readonly object _lock = new object();
    
    /// <summary>
    /// 构造函数
    /// </summary>
    /// <param name="config">连接配置</param>
    public SocketManager(SocketConfig? config = null)
    {
        _config = config ?? new SocketConfig();
    }
    
    /// <summary>
    /// 设置状态回调
    /// </summary>
    /// <param name="callback">状态回调接口</param>
    public void SetCallback(ISocketStateCallback? callback)
    {
        _callback = callback;
    }
    
    /// <summary>
    /// 更新Socket配置
    /// </summary>
    /// <param name="config">新的配置</param>
    public void UpdateConfig(SocketConfig config)
    {
        if (config == null)
            throw new ArgumentNullException(nameof(config));
            
        if (!config.IsValid())
            throw new ArgumentException("配置参数无效", nameof(config));
            
        lock (_lock)
        {
            // 如果当前已连接，先断开连接
            if (_isConnected)
            {
                _callback?.OnSocketMessageReceived("配置已更新，断开当前连接");
                Disconnect();
            }
            
            _config = config;
            _callback?.OnSocketMessageReceived($"配置已更新: {config}");
        }
    }
    
    /// <summary>
    /// 连接到服务器
    /// </summary>
    /// <returns>连接任务</returns>
    public async Task<bool> ConnectAsync()
    {
        lock (_lock)
        {
            if (_isConnected)
            {
                _callback?.OnSocketError("Socket已连接，无需重复连接");
                return true;
            }
        }

        return await ConnectWithRetryAsync();
    }
    
    /// <summary>
    /// 带重连机制的连接
    /// </summary>
    /// <returns>连接结果</returns>
    private async Task<bool> ConnectWithRetryAsync()
    {
        for (int attempt = 0; attempt <= _config.MaxReconnectAttempts; attempt++)
        {
            try
            {
                _callback?.OnSocketMessageReceived($"开始连接Socket服务器 {_config.ServerAddress}:{_config.ServerPort} (第{attempt + 1}次尝试)");
                
                _tcpClient = new TcpClient();
                _cancellationTokenSource = new CancellationTokenSource();
                
                // 解析服务器地址
                IPAddress ipAddress;
                if (!IPAddress.TryParse(_config.ServerAddress, out ipAddress))
                {
                    // 如果不是有效的IP地址，尝试解析域名
                    var addresses = await Dns.GetHostAddressesAsync(_config.ServerAddress);
                    if (addresses == null || addresses.Length == 0)
                    {
                        throw new Exception($"无法解析服务器地址: {_config.ServerAddress}");
                    }
                    ipAddress = addresses[0];
                }
                
                // 设置连接超时
                var connectTask = _tcpClient.ConnectAsync(ipAddress, _config.ServerPort);
                var timeoutTask = Task.Delay(_config.ConnectTimeoutMs);
                
                if (await Task.WhenAny(connectTask, timeoutTask) == timeoutTask)
                {
                    throw new TimeoutException("连接超时");
                }
                
                lock (_lock)
                {
                    _isConnected = true;
                }
                
                _callback?.OnSocketStateChanged(true);
                _callback?.OnSocketMessageReceived("Socket连接成功");
                
                // 启动数据接收循环
                _ = Task.Run(() => ReceiveDataAsync(_cancellationTokenSource.Token));
                
                // 发送初始消息
                await SendMessageAsync("客户端连接成功");
                
                return true;
            }
            catch (Exception ex)
            {
                _callback?.OnSocketError($"连接失败 (第{attempt + 1}次): {ex.Message}");
                
                _tcpClient?.Dispose();
                _tcpClient = null;
                
                if (attempt < _config.MaxReconnectAttempts)
                {
                    await Task.Delay(_config.ReconnectDelayMs);
                }
            }
        }
        
        lock (_lock)
        {
            _isConnected = false;
        }
        _callback?.OnSocketStateChanged(false);
        return false;
    }
    
    /// <summary>
    /// 断开连接
    /// </summary>
    public void Disconnect()
    {
        try
        {
            if (!_isConnected)
            {
                _callback?.OnSocketMessageReceived("Socket未连接");
                return;
            }
            
            _callback?.OnSocketMessageReceived("正在断开Socket连接");
            
            // 取消数据接收任务
            _cancellationTokenSource?.Cancel();
            
            // 关闭TCP连接
            _tcpClient?.Close();
            _tcpClient?.Dispose();
            _tcpClient = null;
            
            _cancellationTokenSource?.Dispose();
            _cancellationTokenSource = null;
            
            _isConnected = false;
            _callback?.OnSocketStateChanged(false);
            _callback?.OnSocketMessageReceived("Socket连接已断开");
        }
        catch (Exception ex)
        {
            _callback?.OnSocketError($"断开连接出错: {ex.Message}");
        }
    }
    
    /// <summary>
    /// 发送消息
    /// </summary>
    /// <param name="message">要发送的消息</param>
    /// <returns>发送任务</returns>
    public async Task<bool> SendMessageAsync(string message)
    {
        try
        {
            if (!_isConnected || _tcpClient?.Connected != true)
            {
                _callback?.OnSocketError("Socket未连接，无法发送消息");
                return false;
            }
            
            var data = Encoding.UTF8.GetBytes(message);
            var stream = _tcpClient.GetStream();
            await stream.WriteAsync(data, 0, data.Length);
            
            _callback?.OnSocketMessageReceived($"发送消息: {message}");
            return true;
        }
        catch (Exception ex)
        {
            _callback?.OnSocketError($"发送消息错误: {ex.Message}");
            return false;
        }
    }
    
    /// <summary>
    /// 异步接收数据（优化版本）
    /// </summary>
    /// <param name="cancellationToken">取消令牌</param>
    private async Task ReceiveDataAsync(CancellationToken cancellationToken)
    {
        var buffer = new byte[_config.BufferSize];
        
        while (_isConnected && _tcpClient?.Connected == true && !cancellationToken.IsCancellationRequested)
        {
            try
            {
                var stream = _tcpClient.GetStream();
                
                // 检查是否有数据可读取
                if (_tcpClient.Available == 0)
                {
                    // 没有数据时短暂等待，避免频繁轮询
                    await Task.Delay(50, cancellationToken);
                    continue;
                }
                
                // 有数据可读时使用较短的超时
                using var timeoutCts = CancellationTokenSource.CreateLinkedTokenSource(cancellationToken);
                timeoutCts.CancelAfter(3000); // 3秒超时
                
                int bytesRead = await stream.ReadAsync(buffer, 0, buffer.Length, timeoutCts.Token);
                
                if (bytesRead > 0)
                {
                    string message = Encoding.UTF8.GetString(buffer, 0, bytesRead);
                    _callback?.OnSocketMessageReceived($"收到服务器消息: {message}");
                }
                else
                {
                    // 服务器关闭连接
                    _callback?.OnSocketMessageReceived("服务器主动关闭了连接");
                    break;
                }
            }
            catch (OperationCanceledException) when (cancellationToken.IsCancellationRequested)
            {
                // 正常取消（用户手动断开或应用关闭）
                _callback?.OnSocketMessageReceived("数据接收任务已取消");
                break;
            }
            catch (OperationCanceledException)
            {
                // 读取超时，但连接仍然有效，继续等待
                // 这种情况下不需要重连，只是没有数据可读
                continue;
            }
            catch (System.IO.IOException ioEx)
            {
                _callback?.OnSocketError($"网络 IO 错误: {ioEx.Message}");
                _callback?.OnSocketError("网络连接中断，尝试重连");
                _ = Task.Run(() => ReconnectAsync());
                break;
            }
            catch (SocketException sockEx)
            {
                _callback?.OnSocketError($"Socket 错误: {sockEx.Message}");
                _callback?.OnSocketError("Socket 连接错误，尝试重连");
                _ = Task.Run(() => ReconnectAsync());
                break;
            }
            catch (Exception ex)
            {
                _callback?.OnSocketError($"未知错误: {ex.Message}");
                // 对于其他类型的错误，谨慎处理，不立即重连
                await Task.Delay(1000, cancellationToken);
                continue;
            }
        }
        
        // 连接已断开
        if (_isConnected)
        {
            lock (_lock)
            {
                _isConnected = false;
            }
            _callback?.OnSocketStateChanged(false);
            _callback?.OnSocketMessageReceived("Socket连接已断开");
        }
    }
    
    /// <summary>
    /// 自动重连
    /// </summary>
    private async Task ReconnectAsync()
    {
        lock (_lock)
        {
            if (!_isConnected)
                return; // 已经断开或正在重连
                
            _isConnected = false;
        }
        
        _callback?.OnSocketStateChanged(false);
        
        // 等待一段时间再重连
        await Task.Delay(_config.ReconnectDelayMs);
        
        // 尝试重连
        await ConnectWithRetryAsync();
    }
    
    /// <summary>
    /// 获取连接状态
    /// </summary>
    /// <returns>是否已连接</returns>
    public bool IsConnected => _isConnected;
    
    /// <summary>
    /// 释放资源
    /// </summary>
    public void Dispose()
    {
        Disconnect();
    }
}